import merge from 'lodash-es/merge.js';
import { useWebSocket } from '@vueuse/core';

export default class WS {
  constructor(url, options) {
    const opt = {
      immediate: true,
      autoClose: true,
      autoReconnect: { retries: 3, delay: 10e3 },
      heartbeat: { message: 'heart beat', interval: 10e3, pongTimeout: 3e3 },
      onConnected: () => {},
      onDisconnected: () => {},
      onError: () => {},
      onMessage: () => {},
    };

    function trigger(obj, name, params) {
      return obj && typeof obj[name] === 'function' ? obj[name](params) : undefined;
    }

    function parseJson(json) {
      if (typeof json === 'string' && /^\[.*]$|^{.*}$/.test(json)) {
        let defaultValue = /^\[.*]$/.test(json) ? [] : {};
        let res;
        try {
          res = JSON.parse(json);
          return res ? res : defaultValue;
        } catch (error) {
          return defaultValue;
        }
      }
      return json;
    }

    options = merge({}, opt, options);

    let { ws, send, close } = useWebSocket(
      url,
      Object.assign({}, options, {
        onConnected: (ws) => {
          trigger(options, 'onConnected', ws);
        },
        onDisconnected: (ws, e) => {
          trigger(options, 'onDisconnected', e);
        },
        onError: (ws, e) => {
          trigger(options, 'onError', e);
        },
        onMessage: (ws, e) => {
          trigger(options, 'onMessage', parseJson(e.data));
        },
      })
    );

    this.ws = ws;
    this.send = send;
    this.close = close;
    this.destroy = function () {
      if (typeof this.close === 'function') {
        this.close();
      }
      this.ws = ws = null;
      this.send = send = null;
      this.close = close = null;
      this.destroy = null;
    };
  }
}
